import { Vector2D } from "./Vector2D.js";

/**
 * 
 * @param {WebGLRenderingContext} gl 
 * @param {String} vertex 
 * @param {String} fragment 
 */
export function attach(gl, vertex, fragment) {
  const vertexShader = gl.createShader(gl.VERTEX_SHADER)
  gl.shaderSource(vertexShader, vertex)
  gl.compileShader(vertexShader)
  
  let success = gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS);
  if (!success) {
    console.log(gl.getShaderInfoLog(vertexShader));
  }
 

  const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
  gl.shaderSource(fragmentShader, fragment);
  gl.compileShader(fragmentShader);

  success = gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS);
  if (!success) {
    console.log(gl.getShaderInfoLog(fragmentShader));
  }

  const program = gl.createProgram()
  gl.attachShader(program, vertexShader)
  gl.attachShader(program, fragmentShader)
  gl.linkProgram(program)
  gl.useProgram(program)

  return program
}

function draw(
  points,
  ctx,
  { strokeStyle = "black", fillStyle = null, close = false } = {}
) {
  ctx.strokeStyle = strokeStyle;
  ctx.beginPath();
  ctx.moveTo(...points[0]);
  for (let i = 1; i < points.length; i++) {
    ctx.lineTo(...points[i]);
  }
  if (close) ctx.closePath();
  if (fillStyle) {
    ctx.fillStyle = fillStyle;
    ctx.fill();
  }
  ctx.stroke();
}

export function parametric(xFunc, yFunc) {
  return function (start, end, seg = 100, ...args) {
    const points = [];
    for (let i = 0; i <= seg; i++) {
      const p = i / seg;
      const t = start * (1 - p) + end * p;
      const x = xFunc(t, ...args);
      const y = yFunc(t, ...args);
      points.push([x, y]);
    }
    return {
      draw: draw.bind(null, points),
      points,
    };
  };
}

/**
 * 
 * @param {Vector2D} p1 
 * @param {Vector2D} p2 
 * @param {Vector2D} p3 
 * @param {Vector2D} point 
 */
export function inTriangle(p1, p2, p3, point) {
  const a = p2.copy().sub(p1)
  const b = p3.copy().sub(p2)
  const c = p1.copy().sub(p3)

  const u1 = point.copy().sub(p1)
  const u2 = point.copy().sub(p2)
  const u3 = point.copy().sub(p3)

  const s1 = Math.sign(a.cross(u1))
  let p = a.dot(u1) / a.length ** 2
  if (s1 === 0 && p >=0 && p <= 1) return true

  const s2 = Math.sign(b.cross(u2))
  p = b.dot(u2) / b.length ** 2
  if (s2 === 0 && p >=0 && p <= 1) return true

  const s3 = Math.sign(c.cross(u3))
  p = c.dot(u3) / c.length ** 2
  if (s3 === 0 && p >=0 && p <= 1) return true

  return s1 === s2 && s2 === s3
}

function isPointInPath({ vertices, cells }, point) {
  for (let i = 0; i < cells.length; i += 3) {
    const p1 = new Vector2D(...vertices[cells[i]])
    const p2 = new Vector2D(...vertices[cells[i + 1]])
    const p3 = new Vector2D(...vertices[cells[i + 2]])
    if (inTriangle(p1, p2, p3, point)) {
      return true
    }
  }
  return false
}